package com.freework.sys.table.service;

import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.annotation.Resource;

import org.apache.commons.beanutils.ConvertUtils;
import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Service;
import org.springframework.util.ResourceUtils;
import org.springframework.util.StringUtils;

import com.freework.sys.cache.CacheProviderManager;
import com.freework.sys.dic.service.DicServiceI;
import com.freework.sys.dic.vo.DicVO;
import com.freework.sys.permissions.external.exception.AppException;
import com.freework.sys.table.vo.ColumnTypeInfo;
import com.freework.sys.table.vo.PageFormVO;
import com.freework.sys.table.vo.PageGridVO;
import com.freework.sys.table.vo.PageVO;
import com.freework.sys.table.vo.SysDiccolumnVO;
import com.freework.util.FileUtil;
import com.freework.util.MapUtil;
import com.freework.util.XMLUtil;

import constant.CacheKeyName;
@Service
public class DicTableReadXMLSeriviceImpi implements DicTableReadXMLSeriviceI{
	@Resource(name = "dic.service.DicService")
	DicServiceI service = null;

	@Resource(name="dic.table.columnType")
	Map<String,ColumnTypeInfo> columnType=null;
	

	public void setColumnType(Map<String, ColumnTypeInfo> columnType) {
		this.columnType = columnType;
	}
	
	public void setService(DicServiceI service) {
		this.service = service;
	}

	private Class getType(String fieldtype, String propertycode)
			throws AppException {
		DicVO dicVO = service.findTableDateByCode("sys_formfield", fieldtype);
		if (dicVO == null)
			return String.class;
		dicVO = service.findTableDateByCode("sys_formfieldproperty", dicVO
				.getId(), propertycode);
		if (dicVO == null)
			return String.class;
		Object datatype = DicTablePageCfgServiceI.typemap.get(dicVO
				.get("datatype"));
		if (datatype == null)
			return String.class;
		else {
			return datatype.getClass();
		}
	}

	private void fieldDataTypeConvert(Map field) throws AppException {
		Set keys = field.keySet();
		String fieldtype = (String) field.get("a00type");

		for (Object key : keys) {
			Object value = field.get(key);
			if (value != null) {
				value = ConvertUtils.convert((String) value, getType(fieldtype,(String) key));
				field.put(key, value);
			}
		}
		field.put("type", fieldtype);
		//field.remove("a00type");
	}

	private PageFormVO mapToForm(Map formMap) throws AppException {

		PageFormVO form = new PageFormVO();
		form.setTitle((String) formMap.get("title"));
		form.setLabelAlign((String) formMap.get("labelAlign"));
		form.setLabelSeparator((String) formMap.get("labelSeparator"));

		Object colspacing = formMap.get("colspacing");
		if (colspacing != null)
			form.setColspacing(Integer.parseInt(colspacing.toString()));

		Object colnum = formMap.get("colnum");
		if (colnum != null)
			form.setColnum(Integer.parseInt(colnum.toString()));

		Object rowpacing = formMap.get("rowpacing");
		if (rowpacing != null)
			form.setRowpacing(Integer.parseInt(rowpacing.toString()));

		Object labelWidth = formMap.get("labelWidth");
		if (labelWidth != null)
			form.setLabelWidth(Integer.parseInt(labelWidth.toString()));
		List<Map> fields = (List<Map>) formMap.get("field");
		for (Map map : fields) {
			fieldDataTypeConvert(map);
		}
		form.setField(fields);
		return form;
	}
	
	
	public PageGridVO mapToGrid(Map gridMap){
		PageGridVO grid=new PageGridVO();
		Map map=(Map) gridMap.get("colModels");
		grid.setColModel((List<Map>) map.get("col"));
		map=(Map) gridMap.get("dataRecords");
		grid.setDataRecord((List<Map>) map.get("record"));
		return grid;
	}
	
	public void addDataRecordKeycolumn(List<Map> dataRecords,String tablename,SysDiccolumnVO keycolumn){
		boolean pand=true;
		if(keycolumn==null)
			return ;
		for (Map map2 : dataRecords) {
			if(keycolumn.getName().equals(map2.get("name"))){
				pand=false;
				break;
			}
		}
		if(pand){
				String datatype = keycolumn.getDatatype();
				if (datatype.equals("n")) {
					if (keycolumn.getScale() != null && keycolumn.getScale().intValue() != 0) {
						datatype = "n2";
					}
				}	
				datatype=columnType.get(datatype).getPrimitiveType().toLowerCase();
				dataRecords.add(MapUtil.asMap("name",keycolumn.getName(),"type",datatype));
			
	
		}
	}
	public void addFormKeycolumn(List<Map> fields,String keycolumn){
		boolean pand=true;
		if(keycolumn==null||keycolumn.equals(""))
			return ;
		for (Map map2 : fields) {
			if(keycolumn.equals(map2.get("name"))){
				pand=false;
				break;
			}
		}
		if(pand){
			fields.add(MapUtil.asMap("name",keycolumn,"type","hidden"));
		}
	}
	
	
	public PageVO getCache(String tablename,long lastModified){
		Map map=CacheProviderManager.get(Map.class, "dic_table_info_cache", CacheKeyName.TABLE_PAGE);
		if(map==null)
			return null;
		PageVO page	=(PageVO) map.get(tablename);
		if(page!=null&&page.getLastLoadTime()<=lastModified){
			return page.clone();
		}else
			return null;
	}
	
	public void addCache(PageVO page){
		HashMap map=CacheProviderManager.get(HashMap.class, "dic_table_info_cache", CacheKeyName.TABLE_PAGE);
		if(map==null){
			map=new HashMap();
			CacheProviderManager.set("dic_table_info_cache", CacheKeyName.TABLE_PAGE, map);
		}
		map.put(page.getTablename(), page);
	}
	
	private PageVO getPage(File file,String tablename) throws AppException{
		Map<String, Object> map =null;
		try {
			 map = XMLUtil.xmlToMap(file,"UTF-8");
		} catch (IOException e) {
			e.printStackTrace();
			throw new AppException(e);
		}
		PageVO page = new PageVO(tablename);
		page.setForm(mapToForm((Map) map.get("form")));
		page.setGrid(mapToGrid((Map) map.get("grid")));
		return page;
	}
	
	private PageVO predefineXml(String tablename) throws AppException{
	ClassPathResource cr = new ClassPathResource("com/freework/sys/table/predefineXml/"+tablename+".xml");
	 if(cr.exists()){
		 try {
			return getPage(cr.getFile(),tablename);
		} catch (IOException e) {
			e.printStackTrace();
			return null;
		}
	 }else
		 return null;
	}
	
	
	
	public  PageVO xmlToPage(String tablename) throws AppException {
		String path = FileUtil.getFileSysPath("tablexml") + tablename + ".xml";
		File file=new File(path);
		if (file.isFile()&&file.exists()) {
			Map<String, Object> map =null;
			long lastModified=file.lastModified();
			PageVO page	=getCache(tablename,lastModified);
			if(page!=null)
				return page.clone();
			page=getPage(file,tablename);
			page.setLastLoadTime(lastModified);
			addCache(page);
			return page.clone();
		} else{
			return predefineXml(tablename);
		}
	}
}
